package com.hfy.pcberpbackend.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hfy.pcberpbackend.entity.Quote;
import com.hfy.pcberpbackend.entity.QuoteItem;
import com.hfy.pcberpbackend.entity.QuoteStatusLog;
import com.hfy.pcberpbackend.entity.Customer;
import com.hfy.pcberpbackend.mapper.QuoteMapper;
import com.hfy.pcberpbackend.mapper.QuoteItemMapper;
import com.hfy.pcberpbackend.mapper.QuoteStatusLogMapper;
import com.hfy.pcberpbackend.mapper.CustomerMapper;
import com.hfy.pcberpbackend.service.QuoteService;
import com.hfy.pcberpbackend.dto.*;
import com.hfy.pcberpbackend.common.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.StrUtil;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 报价单Service实现类
 */
@Slf4j
@Service
public class QuoteServiceImpl extends ServiceImpl<QuoteMapper, Quote> implements QuoteService {
    
    @Autowired
    private QuoteItemMapper quoteItemMapper;
    
    @Autowired
    private QuoteStatusLogMapper quoteStatusLogMapper;
    
    @Autowired
    private CustomerMapper customerMapper;
    
    @Override
    public PageResult<QuoteVO> getQuotePage(QuoteQueryDTO query) {
        log.info("分页查询报价单列表，查询条件：{}", query);
        
        Page<Quote> page = new Page<>(query.getPage(), query.getSize());
        IPage<QuoteVO> result = baseMapper.selectQuotePage(page, query);
        
        return PageResult.of(result.getRecords(), result.getTotal(), 
                           result.getCurrent(), result.getSize());
    }
    
    @Override
    public PageResult<QuoteVO> getQuoteRecordPage(QuoteQueryDTO query) {
        log.info("分页查询报价记录列表，查询条件：{}", query);
        
        Page<Quote> page = new Page<>(query.getPage(), query.getSize());
        IPage<QuoteVO> result = baseMapper.selectQuoteRecordPage(page, query);
        
        return PageResult.of(result.getRecords(), result.getTotal(), 
                           result.getCurrent(), result.getSize());
    }
    
    @Override
    public QuoteVO getQuoteById(Long id) {
        log.info("根据ID获取报价单详情，ID：{}", id);
        
        QuoteVO quoteVO = baseMapper.selectQuoteDetail(id);
        if (quoteVO == null) {
            throw new RuntimeException("报价单不存在");
        }
        
        // 查询物料明细
        List<QuoteItemVO> items = quoteItemMapper.selectByQuoteId(id);
        quoteVO.setItems(items);
        
        return quoteVO;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createQuote(QuoteCreateDTO createDTO, String operator) {
        log.info("新增报价单，操作人：{}，数据：{}", operator, createDTO);
        
        // 验证客户是否存在
        Customer customer = customerMapper.selectById(createDTO.getCustomerCode());
        if (customer == null) {
            throw new RuntimeException("客户不存在");
        }
        
        // 创建报价单主表
        Quote quote = new Quote();
        BeanUtils.copyProperties(createDTO, quote);
        quote.setQuoteCode(generateQuoteCode());
        quote.setCustomerName(customer.getCustomerName());
        quote.setStatus("DRAFT");
        quote.setCreatedBy(operator);
        quote.setUpdatedBy(operator);
        
        // 计算总金额
        calculateTotalAmount(quote, createDTO.getItems());
        
        // 保存主表
        save(quote);
        
        // 保存物料明细
        if (createDTO.getItems() != null && !createDTO.getItems().isEmpty()) {
            saveQuoteItems(quote.getId(), createDTO.getItems());
        }
        
        // 记录状态变更日志
        saveStatusLog(quote.getId(), null, "DRAFT", "创建报价单", operator);
        
        return quote.getId();
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQuote(QuoteUpdateDTO updateDTO, String operator) {
        log.info("更新报价单，操作人：{}，数据：{}", operator, updateDTO);
        
        // 检查报价单是否存在
        Quote existingQuote = getById(updateDTO.getId());
        if (existingQuote == null) {
            throw new RuntimeException("报价单不存在");
        }
        
        // 只有草稿状态才能修改
        if (!"DRAFT".equals(existingQuote.getStatus())) {
            throw new RuntimeException("只有草稿状态的报价单才能修改");
        }
        
        // 验证客户是否存在
        Customer customer = customerMapper.selectById(updateDTO.getCustomerCode());
        if (customer == null) {
            throw new RuntimeException("客户不存在");
        }
        
        // 更新主表
        Quote quote = new Quote();
        BeanUtils.copyProperties(updateDTO, quote);
        quote.setCustomerName(customer.getCustomerName());
        quote.setUpdatedBy(operator);
        
        // 计算总金额
        calculateTotalAmount(quote, updateDTO.getItems());
        
        updateById(quote);
        
        // 删除原有物料明细
        quoteItemMapper.deleteByQuoteId(updateDTO.getId());
        
        // 重新保存物料明细
        if (updateDTO.getItems() != null && !updateDTO.getItems().isEmpty()) {
            saveQuoteItems(updateDTO.getId(), updateDTO.getItems());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitQuote(Long id, String operator) {
        log.info("提交报价单，ID：{}，操作人：{}", id, operator);
        
        Quote quote = getById(id);
        if (quote == null) {
            throw new RuntimeException("报价单不存在");
        }
        
        if (!"DRAFT".equals(quote.getStatus())) {
            throw new RuntimeException("只有草稿状态的报价单才能提交");
        }
        
        // 更新状态
        quote.setStatus("SUBMITTED");
        quote.setUpdatedBy(operator);
        updateById(quote);
        
        // 记录状态变更日志
        saveStatusLog(id, "DRAFT", "SUBMITTED", "提交报价单", operator);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approveQuote(Long id, String reason, String operator) {
        log.info("批准报价单，ID：{}，原因：{}，操作人：{}", id, reason, operator);
        
        Quote quote = getById(id);
        if (quote == null) {
            throw new RuntimeException("报价单不存在");
        }
        
        if (!"SUBMITTED".equals(quote.getStatus())) {
            throw new RuntimeException("只有已提交状态的报价单才能批准");
        }
        
        // 更新状态
        quote.setStatus("APPROVED");
        quote.setUpdatedBy(operator);
        updateById(quote);
        
        // 记录状态变更日志
        saveStatusLog(id, "SUBMITTED", "APPROVED", reason, operator);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rejectQuote(Long id, String reason, String operator) {
        log.info("拒绝报价单，ID：{}，原因：{}，操作人：{}", id, reason, operator);
        
        Quote quote = getById(id);
        if (quote == null) {
            throw new RuntimeException("报价单不存在");
        }
        
        if (!"SUBMITTED".equals(quote.getStatus())) {
            throw new RuntimeException("只有已提交状态的报价单才能拒绝");
        }
        
        // 更新状态
        quote.setStatus("REJECTED");
        quote.setUpdatedBy(operator);
        updateById(quote);
        
        // 记录状态变更日志
        saveStatusLog(id, "SUBMITTED", "REJECTED", reason, operator);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteQuote(Long id) {
        log.info("删除报价单，ID：{}", id);
        
        Quote quote = getById(id);
        if (quote == null) {
            throw new RuntimeException("报价单不存在");
        }
        
        // 只有草稿状态才能删除
        if (!"DRAFT".equals(quote.getStatus())) {
            throw new RuntimeException("只有草稿状态的报价单才能删除");
        }
        
        // 删除物料明细
        quoteItemMapper.deleteByQuoteId(id);
        
        // 删除主表
        removeById(id);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteQuotes(List<Long> ids) {
        log.info("批量删除报价单，IDs：{}", ids);
        
        if (ids == null || ids.isEmpty()) {
            throw new RuntimeException("删除的ID列表不能为空");
        }
        
        // 检查所有报价单状态
        List<Quote> quotes = baseMapper.selectByIds(ids);
        for (Quote quote : quotes) {
            if (!"DRAFT".equals(quote.getStatus())) {
                throw new RuntimeException("报价单【" + quote.getQuoteCode() + "】不是草稿状态，无法删除");
            }
        }
        
        // 批量删除物料明细
        for (Long id : ids) {
            quoteItemMapper.deleteByQuoteId(id);
        }
        
        // 批量删除主表
        removeByIds(ids);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long copyQuote(Long id, String operator) {
        log.info("复制报价单，原ID：{}，操作人：{}", id, operator);
        
        QuoteVO originalQuote = getQuoteById(id);
        
        // 创建新报价单
        QuoteCreateDTO createDTO = new QuoteCreateDTO();
        BeanUtils.copyProperties(originalQuote, createDTO);
        createDTO.setRemark("复制自：" + originalQuote.getQuoteCode());
        
        // 复制物料明细
        if (originalQuote.getItems() != null) {
            List<QuoteItemDTO> items = originalQuote.getItems().stream()
                    .map(item -> {
                        QuoteItemDTO dto = new QuoteItemDTO();
                        BeanUtils.copyProperties(item, dto);
                        return dto;
                    })
                    .collect(Collectors.toList());
            createDTO.setItems(items);
        }
        
        return createQuote(createDTO, operator);
    }
    
    @Override
    public String generateQuoteCode() {
        String datePrefix = "QT" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        Integer maxSequence = baseMapper.getMaxSequenceByDate(datePrefix);
        int nextSequence = (maxSequence == null ? 0 : maxSequence) + 1;
        return datePrefix + String.format("%03d", nextSequence);
    }
    
    /**
     * 保存物料明细
     */
    private void saveQuoteItems(Long quoteId, List<QuoteItemDTO> itemDTOs) {
        List<QuoteItem> items = itemDTOs.stream()
                .map(dto -> {
                    QuoteItem item = new QuoteItem();
                    BeanUtils.copyProperties(dto, item);
                    item.setQuoteId(quoteId);
                    return item;
                })
                .collect(Collectors.toList());
        
        quoteItemMapper.batchInsert(items);
    }
    
    /**
     * 计算总金额
     */
    private void calculateTotalAmount(Quote quote, List<QuoteItemDTO> items) {
        if (items == null || items.isEmpty()) {
            quote.setTotalAmount(BigDecimal.ZERO);
            quote.setTotalTaxAmount(BigDecimal.ZERO);
            return;
        }
        
        BigDecimal totalAmount = items.stream()
                .filter(item -> item.getTotalAmount() != null)
                .map(QuoteItemDTO::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        quote.setTotalAmount(totalAmount);
        
        // 计算含税金额
        if (quote.getIsTaxIncluded() == 1) {
            quote.setTotalTaxAmount(totalAmount.multiply(new BigDecimal("1.13")));
        } else {
            quote.setTotalTaxAmount(totalAmount);
        }
    }
    
    /**
     * 保存状态变更日志
     */
    private void saveStatusLog(Long quoteId, String oldStatus, String newStatus, String reason, String operator) {
        QuoteStatusLog log = new QuoteStatusLog();
        log.setQuoteId(quoteId);
        log.setOldStatus(oldStatus);
        log.setNewStatus(newStatus);
        log.setChangeReason(reason);
        log.setOperator(operator);
        quoteStatusLogMapper.insert(log);
    }
} 